package com.bnq.logc.upload

import android.util.Log
import cn.ucloud.ufile.UfileClient
import cn.ucloud.ufile.api.`object`.ObjectConfig
import cn.ucloud.ufile.auth.ObjectAuthorization
import cn.ucloud.ufile.auth.UfileObjectLocalAuthorization
import cn.ucloud.ufile.bean.PutObjectResultBean
import cn.ucloud.ufile.bean.UfileErrorBean
import cn.ucloud.ufile.http.BaseHttpCallback
import cn.ucloud.ufile.http.HttpClient
import cn.ucloud.ufile.util.MimeTypeUtil
import com.bnq.logc.LogcManager
import com.bnq.logc.config.LogcConfig
import okhttp3.*
import okio.Buffer
import java.io.File
import java.io.IOException
import java.util.concurrent.Executors
import java.util.concurrent.TimeUnit


object UfileClientManager {

    lateinit var OBJECT_AUTHORIZER: ObjectAuthorization

    lateinit var OBJECT_CONFIG: ObjectConfig

    lateinit var mBucketName:String

    //lateinit var mCloudParentDir:String

    lateinit var mOkHttpClient: OkHttpClient

    lateinit var mConfig:LogcConfig

    init {
        initConfig()
    }

    private fun initConfig(){
        UfileClient.configure( UfileClient.Config(
                 HttpClient.Config(4, 60, TimeUnit.SECONDS)
            .setTimeout(60 * 1000,60 * 1000,60 * 1000)
            .setExecutorService(Executors.newCachedThreadPool())
            //.addInterceptor(okhttp3拦截器)
            /*.addNetInterceptor(object :Interceptor{
                override fun intercept(chain: Interceptor.Chain): Response {
                    val request = chain.request()
                    val url = request.url()
                    println("request url: $url")
                    return chain.proceed(request)
                }
            })*/.apply {
                         if(LogcManager.getConfig().mIsDebug){
                             addInterceptor(object :Interceptor{

                                 private val TAG = "Logc-Uc"

                                 override fun intercept(chain: Interceptor.Chain): Response {
                                     val request = chain.request()
                                     val key = request.hashCode().toString()
                                     var response:Response
                                     try{
                                         processRequest(key,request)
                                         response = chain.proceed(request)
                                         response = processResponseBody(key,response)
                                     }catch (e: IOException){
                                         processError(key,request,e)
                                         throw e
                                     }
                                     return response
                                 }

                                 fun processError(key:String,request:Request,e: IOException){
                                     Log.e(TAG,"Http error url:${request.url()}\nkey:${key}\nheaders:${request.headers()}\nerror:${e.message}")
                                 }

                                 fun processRequest(key:String,request:Request):Request{
                                     return request.body()?.let {
                                         val buffer = Buffer()
                                         it.writeTo(buffer)
                                         val originBodyString = buffer.readUtf8()
                                         Log.i(TAG,"Http request url:${request.url()}\nkey:${key}\nheaders:${request.headers()}\nbody:$originBodyString")
                                         request.newBuilder().post(RequestBody.create(it.contentType(),originBodyString)).build()
                                     }?:request
                                 }

                                 fun processResponseBody(key:String,response:Response):Response{
                                     val body = response.body()
                                     if(body != null){
                                         val bodyString = body.string()
                                         val buildResponse =
                                             response.newBuilder().body(ResponseBody.create(body.contentType(),bodyString)).build()
                                         Log.i(TAG,"Http response url:${response.request().url()}\nkey:${key}\nheaders:${response.headers()}\nbody:$bodyString\n")
                                         return buildResponse
                                     }else{
                                         Log.i(TAG,"Http response url:${response.request().url()}\nkey:${key}\nheaders:${response.headers()}\n")
                                         return response
                                     }
                                 }
                             })
                         }
                     }
            )).apply {
            mOkHttpClient = httpClient.okHttpClient
        }

        val config: LogcConfig = LogcManager.getConfig()
        this.mConfig = config

        OBJECT_AUTHORIZER = UfileObjectLocalAuthorization(
            config.mUploadPublicKey, config.mUploadPrivateKey
        )

        OBJECT_CONFIG = ObjectConfig(config.mCustomHost)

        mBucketName = config.mBucketName

        //mCloudParentDir = config.getCloudParentDir()
    }

    private fun getCloudName(file: File):String{
        return "${mConfig.getCloudParentDir(file)}/${file.name}"
    }

    fun upload(file: File, callback:BaseHttpCallback<PutObjectResultBean, UfileErrorBean> ):String{
        val cloudName = getCloudName(file)
        UfileClient.`object`(OBJECT_AUTHORIZER, OBJECT_CONFIG)
            .putObject(file, MimeTypeUtil.getMimeType(file.name))
            .nameAs(cloudName)
            .toBucket(mBucketName)
            /**
             * 是否上传校验MD5, Default = true
             */
            //   .withVerifyMd5(false)
            /**
             * 指定progress callback的间隔, Default = 每秒回调
             */
            //   .withProgressConfig(ProgressConfig.callbackWithPercent(10))
            .executeAsync(callback)
        return cloudName
    }

    fun uploadCommon(file: File,cloudPathName:String, callback:BaseHttpCallback<PutObjectResultBean, UfileErrorBean> ):String{
        UfileClient.`object`(OBJECT_AUTHORIZER, OBJECT_CONFIG)
            .putObject(file, MimeTypeUtil.getMimeType(file.name))
            .nameAs(cloudPathName)
            .toBucket(mBucketName)
            /**
             * 是否上传校验MD5, Default = true
             */
            //   .withVerifyMd5(false)
            /**
             * 指定progress callback的间隔, Default = 每秒回调
             */
            //   .withProgressConfig(ProgressConfig.callbackWithPercent(10))
            .executeAsync(callback)
        return cloudPathName
    }

    fun post(url:String,headers:Map<String,String>?,body:String,callback: Callback){
        val requestBody = RequestBody.create(MediaType.parse("application/json; charset=utf-8"),body)
        val requestBuilder = Request.Builder()
            .addHeader("content-type", "application/json")
            .post(requestBody)
            .url(url)
        if(headers?.isNotEmpty() == true){
            headers.forEach {entry ->
                requestBuilder.header(entry.key,entry.value)
            }
        }
        val request = requestBuilder.build()
        mOkHttpClient.newCall(request).enqueue(callback)
    }
}